package com.yunhe.common.repository.data.impl;

import com.yunhe.common.repository.data.BaseJpaRepository;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;

/**
 * 基础JPA仓库实现类
 * @author liuronglei
 */
@Transactional(readOnly = true)
public class BaseJpaRepositoryImpl<T, ID extends Serializable>
        extends SimpleJpaRepository<T, ID> implements BaseJpaRepository<T, ID> {
    private int BATCH_SIZE = 500;
    private final EntityManager em;

    public BaseJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation,
                                 EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.em = entityManager;
    }

    @Override
    @Transactional
    public<S extends T> S insert(S entity) {
        em.persist(entity);
        return entity;
    }

    @Override
    @Transactional
    public <S extends T> List<S> insert(List<S> var1) {
        Iterator<S> iterator = var1.iterator();
        int index = 0;
        while (iterator.hasNext()){
            em.persist(iterator.next());
            index++;
            if (index % BATCH_SIZE == 0) {
                em.flush();
                em.clear();
            }
        }
        if (index % BATCH_SIZE != 0) {
            em.flush();
            em.clear();
        }
        return var1;
    }

    @Override
    @Transactional
    public <S extends T> S update(S entity) {
        em.merge(entity);
        return entity;
    }

    @Override
    @Transactional
    public <S extends T> List<S> update(List<S> var1) {
        Iterator<S> iterator = var1.iterator();
        int index = 0;
        while (iterator.hasNext()){
            em.merge(iterator.next());
            index++;
            if (index % BATCH_SIZE == 0){
                em.flush();
                em.clear();
            }
        }
        if (index % BATCH_SIZE != 0){
            em.flush();
            em.clear();
        }
        return var1;
    }
}
